package im.oen.boot.api.service;

import im.oen.boot.api.dao.AbsDao;
import im.oen.boot.api.entity.AbsEntity;
import im.oen.boot.common.utils.Checker;
import org.springframework.data.domain.Sort;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author Kevin.Xu
 */
public abstract class AbsService<T extends AbsEntity, ID extends Serializable> {

    /**
     * 每个Service返回自己对于的Dao以供父类通用方法使用
     *
     * @return DAO
     */
    protected abstract AbsDao<T, ID> getDao();

    /**
     * 统计时间范围内的数据量
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 数据量
     */
    public Long countByCreated(long start, long end) {
        return this.getDao().countByCreated(start, end);
    }

    /**
     * 根据ID查询数据
     *
     * @param id 数据ID
     * @return 数据
     */
    public T findById(ID id) {
        Optional<T> tmp = this.getDao().findById(id);
        return tmp.orElse(null);
    }

    /**
     * 根据数据的UUID查询数据
     *
     * @param uuid UUID
     * @return 数据
     */
    public T findByUuid(String uuid) {
        return this.getDao().findByUuid(uuid);
    }

    /**
     * 查询所有的数据
     *
     * @return 所有数据
     */
    public List<T> findAll() {
        return this.getDao().findAll();
    }

    /**
     * 查询所有数据但是需要排序
     *
     * @param sort 排序规则
     * @return 所有数据
     */
    public List<T> findAll(Sort sort) {
        return this.getDao().findAll(sort);
    }

    /**
     * 根据Id列表查询数据
     *
     * @param ids 数据ID列表
     * @return 数据列表
     */
    public List<T> findAllByIds(Iterable<ID> ids) {
        return this.getDao().findAllById(ids);
    }

    /**
     * 根据ID列表批量删除数据
     *
     * @param ids 数据ID列表
     */
    public void deleteByIds(Iterable<ID> ids) {
        if (Checker.isEmpty(ids)) {
            return;
        }

        ids.forEach(id -> {
            this.getDao().deleteById(id);
        });
    }

    /**
     * 统计数据在指定时间内每天的数据量
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 范围内每天的数据量
     */
    public Map<Long, Long> groupDateByCreated(long start, long end) {
        List<Map<String, Long>> data = this.getDao().groupDateByCreated(start, end);
        if (Checker.isEmpty(data)) {
            return new HashMap<>();
        }

        Map<Long, Long> res = new HashMap<>(data.size());
        for (Map<String, Long> map : data) {
            res.put(map.get("item"), map.get("value"));
        }
        return res;
    }
}
